package com.cyan.learn;

import org.junit.Test;

/**
 * 动态规划
 */
public class DynamicTest {

    /**
     * 509丶斐波那契数列
     * 递归
     */
    public int fib(int n) {
        if (n == 0) {
            return 0;
        }
        if (n == 1) {
            return 1;
        }
        return fib(n - 1) + fib(n - 2);
    }

    /**
     * 509丶斐波那契数列
     * 动态规划
     */
    public int fib2(int n) {
        if (n < 2) {
            return n;
        }

        // 动态规划数组dp
        int[] dp = new int[n + 1];
        dp[0] = 0;
        dp[1] = 1;
        for (int i = 2; i < n + 1; i++) {
            dp[i] = dp[i - 1] + dp[i - 2];
        }

        return dp[n];
    }


    /**
     * 70丶爬楼梯
     */
    public int climbStairs(int n) {
        if (n == 1 || n == 2) {
            return n;
        }
        int[] dp = new int[n + 1];
        dp[1] = 1;
        dp[2] = 2;
        for (int i = 3; i < n + 1; i++) {
            dp[i] = dp[i - 1] + dp[i - 2];
        }
        return dp[n];
    }

    @Test
    public void test70() {
        int i = climbStairs(11);
        System.out.println(i);
    }

    /**
     * 746丶使用最小花费爬楼梯
     */
    public int minCostClimbingStairs(int[] cost) {
        int len = cost.length;
        int[] dp = new int[len + 1];

        dp[0] = 0;
        dp[1] = 0;
        for (int i = 2; i < dp.length; i++) {
            dp[i] = Math.min(dp[i - 1] + cost[i - 1], dp[i - 2] + cost[i - 2]);
        }
        return dp[len];
    }


    /**
     * 343丶整数拆分
     */
    public int integerBreak(int n) {
        int[] dp = new int[n + 1];
        dp[2] = 1;

        for (int i = 3; i < n + 1; i++) {
            for (int j = 1; j < i - j; j++) {
                dp[i] = Math.max(dp[i], Math.max(i * (i - j), dp[i - j] * j));
            }
        }
        return dp[n];
    }


    /**
     * 96丶不同的二叉搜索树
     */
    public int numTrees(int n) {
        int[] dp = new int[n + 1];
        dp[0] = 1;
        dp[1] = 1;

        for (int i = 2; i < n + 1; i++) {
            for (int j = 1; j <= i; j++) {
                dp[i] += dp[j - 1] * dp[i - j];
            }
        }
        return dp[n];
    }
}
